package com.mzj.saas.mservice.application.service;

import com.mzj.saas.commons.ApiData;
import com.mzj.saas.commons.ResultBean;
import com.mzj.saas.commons.StatusCode;
import com.mzj.saas.commons.util.StringUtils;
import com.mzj.saas.commons.vo.redis.TokenRedisVo;
import com.mzj.saas.mservice.application.entity.ApprovalProcess;
import com.mzj.saas.mservice.application.entity.ApprovalProcessDetail;
import com.mzj.saas.mservice.application.entity.ApprovalProcessLog;
import com.mzj.saas.mservice.application.repository.*;
import com.mzj.saas.mservice.application.vo.HouseFlowVO;
import com.mzj.saas.mservice.area.repository.AreaRepository;
import com.mzj.saas.mservice.department.entity.Department;
import com.mzj.saas.mservice.department.entity.DepartmentTag;
import com.mzj.saas.mservice.department.repository.DepartmentRepository;
import com.mzj.saas.mservice.department.repository.DepartmentTagRepository;
import com.mzj.saas.mservice.eligible.entity.DepartmentHierarchy;
import com.mzj.saas.mservice.eligible.repository.DepartmentHierarchyRepository;
import com.mzj.saas.redis.RedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class HouseManagerService {
    private static final Logger LOG = LoggerFactory.getLogger(HouseManagerService.class);
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private RedisService redisService;
    @Autowired
    private DepartmentRepository departmentRepository;
    @Autowired
    private DepartmentHierarchyRepository hierarchyRepository;
    @Autowired
    private ApprovalProcessRepository approvalProcessRepository;
    @Autowired
    private ApprovalProcessDefinitionRepository approvalProcessDefinitionRepository;
    @Autowired
    private ApprovalProcessNodeRepository approvalProcessNodeRepository;
    @Autowired
    private ApprovalProcessDetailRepository approvalProcessDetailRepository;
    @Autowired
    private ApprovalProcessUserRepository approvalProcessUserRepository;
    @Autowired
    private ApprovalProcessLogRepository approvalProcessLogRepository;
    @Autowired
    private DepartmentTagRepository departmentTagRepository;
    @Autowired
    private AreaRepository areaRepository;
    @Autowired
    private DepartmentHierarchyRepository departmentHierarchyRepository;
    /*
     *公租房管理表单管理企业公租房流程显示
     * status 0关闭 1开启
     */
    public ResultBean<Object> companyAuditorFlow(String accessToken, Integer pageNumber, Integer pageSize) {
        LOG.info("HouseManagerService companyAuditorFlow accessToken={},pageNumber={},pageSize={}", accessToken,pageNumber,pageSize);
        ResultBean<Object> resultBean = new ResultBean<>();
        resultBean.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        resultBean.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        resultBean.setResultData(Collections.emptyList());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        List<Map<String,Object>> result = new ArrayList<>();
        ApiData<Map<String, Object>> apiData = new ApiData<>();
        try {
            if (tokenRedisVo == null) {
                resultBean.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                resultBean.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return resultBean;
            }
            Optional<Department> existDepartment = departmentRepository.findById(tokenRedisVo.getEnterpriseId());
            if (existDepartment == null) {
                return ResultBean.failedResultWithMsg("部门不存在或已删除");
            }
            DepartmentHierarchy existDepartmentHierarchy = hierarchyRepository.findByOrgId(tokenRedisVo.getEnterpriseId());
            if (existDepartmentHierarchy == null) {
                return ResultBean.failedResultWithMsg("部门机构层级关系不存在或已删除");
            }
            Department company = existDepartment.get();

            int tagId=existDepartmentHierarchy.getTagId().intValue();
            String districtId="";

            String SQL= "select id,name from sys_area where id in " +
                    " (select id from ( select t1.id,if(find_in_set(parent_id, @pids) > 0,@pids := concat(@pids, ',', id),0) as ischild from ( select id,parent_id from `sys_area` t order by parent_id, id ) t1,(select @pids := ? ) t2 ) t3 where ischild != 0) and LEVEL=3 ";

            List<Map<String,Object>> list=new ArrayList<>();

            if(tagId==1){
                 list=jdbcTemplate.queryForList(SQL,company.getProvinceId());
            }else if(tagId==2){
                 list=jdbcTemplate.queryForList(SQL,company.getCityId());
            }else{
                 list=jdbcTemplate.queryForList("select id,name from sys_area where id =?",company.getDistrictId());
            }

            for(Map<String,Object> m : list){
                String district=m.get("id").toString()+",";
                districtId +=district;
            }


            String flowSql="SELECT  pro.district_id,pro.id,pro.`approval_process` AS approvalProcess ,pro.process_tag_name AS processTagName,sys.name,pro.status AS status,pro.`last_update_time` AS lastUpdateTime " +
                    "FROM saas_approval_process pro \n" +
                    "LEFT JOIN sys_area sys ON pro.district_id = sys.id\n" +
                    "WHERE  1=1 ";
        /*    if (districtId==null){
                return ResultBean.failedResultWithMsg("企业所属区不存在！");
            }*/
            flowSql+="  AND  pro.district_id in ( "+districtId.substring(0,districtId.lastIndexOf(","))+")";
            String count = "SELECT COUNT(0) FROM  ("+flowSql+")  c";
            String offsets = "  LIMIT ? OFFSET ? ";
            // 查询总记录数
            Long total = jdbcTemplate.queryForObject(count, Long.class);
            if (total == 0) {
                resultBean.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
                resultBean.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
                resultBean.setResultData(null);
                return resultBean;
            }
            // 查询分页数据
            List<Object> args = new ArrayList<>();
            flowSql+=offsets;
            args.add(pageSize);
            args.add(pageNumber * pageSize);
            List<Map<String, Object>> mapList = jdbcTemplate.queryForList(flowSql,args.toArray());
            for (Map<String, Object> map : mapList) {
                List<HouseFlowVO> houseFlowVOS=new ArrayList<>();
                String[] tagIdList =String.valueOf(map.get("approvalProcess")).split(",");
                String[] tagNameList = String.valueOf(map.get("processTagName")).split("->");
                for (int i = 0;i <tagIdList.length  ; i++) {
                    HouseFlowVO houseFlowVO=new HouseFlowVO();
                    houseFlowVO.setId((Long) map.get("id"));
                    houseFlowVO.setTagId(Long.valueOf(tagIdList[i]));
                    houseFlowVO.setTagName(tagNameList[i]);
                    houseFlowVOS.add(houseFlowVO);
                }
                map.put("flowProcess",houseFlowVOS);
                map.put("typeName","公租房审批流程");
                result.add(map);
            }
            apiData.setData(result);
            apiData.setTotal(total);
            resultBean.setResultData(apiData);
        } catch (Exception e) {
            resultBean.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            resultBean.setMsg(e.getMessage());
        }
        return resultBean;
    }

    /*
     *查找当前节点所有父级节点(包含当前节点)
     */
    public List<Long> allParent(Long id) {
        String sql = "SELECT T2.id FROM (SELECT @r AS _id,(SELECT @r := parent_id FROM `saas_department_hierarchy` WHERE id = _id) AS parent_id,@l := @l + 1 AS lvl FROM (SELECT @r := ?, @l := 0) vars,saas_department_hierarchy h WHERE @r <> 0 AND parent_id >= 0) T1 JOIN saas_department_hierarchy T2 ON T1._id = T2.id  ORDER BY T1.lvl ";
        return jdbcTemplate.queryForList(sql, new Object[]{id}, Long.class);
    }


    /*
     *流程开启关闭
     */
    public ResultBean<Object> closeOrOpenCustomizeFlow(String accessToken,  Long id, Integer status) {
        LOG.info("HouseManagerService closeCustomizeFlow accessToken={},id={},status={}", accessToken, id,status);
        ResultBean<Object> resultBean = new ResultBean<>();
        resultBean.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        resultBean.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        resultBean.setResultData(Collections.emptyList());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                resultBean.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                resultBean.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return resultBean;
            }
           if(id==null||status==null){
               resultBean.setCode(StatusCode.ERROR_CODE_10005.getErrorCode());
               resultBean.setMsg(StatusCode.ERROR_CODE_10005.getErrorMsg());
               return resultBean;
           }
            Optional<ApprovalProcess> approvalProcessOptional = approvalProcessRepository.findById(id);
           if (approvalProcessOptional==null){
               return ResultBean.failedResultWithMsg("流程不存在或是已删除");
           }
            ApprovalProcess approvalProcess = approvalProcessOptional.get();
            approvalProcess.setStatus(status);
            approvalProcess.setLastUpdateTime(new Date());
            approvalProcessRepository.save(approvalProcess);
        } catch (Exception e) {
            resultBean.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            resultBean.setMsg(e.getMessage());
        }
        return resultBean;
    }


    /*
     *设置流程
     */
    public ResultBean<Object> setCompanyAuditorFlow(String accessToken,List<HouseFlowVO> houseFlowVOList) {
        LOG.info("HouseManagerService setCompanyAuditorFlow accessToken={},houseFlowVOList={}", accessToken, houseFlowVOList);
        ResultBean<Object> resultBean = new ResultBean<>();
        resultBean.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        resultBean.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                resultBean.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                resultBean.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return resultBean;
            }
            if (houseFlowVOList == null || houseFlowVOList != null && houseFlowVOList.size() == 0) {
                resultBean.setCode(StatusCode.ERROR_CODE_10005.getErrorCode());
                resultBean.setMsg(StatusCode.ERROR_CODE_10005.getErrorMsg());
                return resultBean;
            }
            LinkedList<HouseFlowVO> linkedList=new LinkedList<>();
            for (int i = houseFlowVOList.size() - 1; i >= 0; i--) {
                linkedList.add(houseFlowVOList.get(i));
            }
            String approvalProcessIds="";
            String processTagName="";
            Long id=null;
            //流程标签id
            List<Long> tagList=new ArrayList<>();
            for (HouseFlowVO houseFlowVO : houseFlowVOList) {
            tagList.add(houseFlowVO.getTagId());
            id=houseFlowVO.getId();
            approvalProcessIds+=houseFlowVO.getTagId()+",";
            processTagName+=houseFlowVO.getTagName()+"->";
            }

            if (id==null){
                return ResultBean.failedResultWithMsg("流程id不能为空");
            }
            if (StringUtils.isBlank(approvalProcessIds)){
                return ResultBean.failedResultWithMsg("流程节点各节点机构id不能为空");
            }
            if (StringUtils.isBlank(processTagName)){
                return ResultBean.failedResultWithMsg("流程标签字符串不能为空");
            }
            Optional<ApprovalProcess> existApprovalProcess = approvalProcessRepository.findById(id);
            if (!existApprovalProcess.isPresent()){
                return ResultBean.failedResultWithMsg("流程信息有误");
            }

            //审批流程表
            ApprovalProcess approvalProcess = existApprovalProcess.get();
            String oldApprovalProcess=approvalProcess.getApprovalProcess();
            approvalProcess.setApprovalProcess(approvalProcessIds.substring(0,approvalProcessIds.lastIndexOf(",")));
            approvalProcess.setProcessTagName(processTagName.substring(0,processTagName.lastIndexOf("->")));
            approvalProcess.setLastUpdateTime(new Date());
            //更新审批流程表流程信息
            ApprovalProcess save = approvalProcessRepository.save(approvalProcess);

            //流程节点发生更改时
            if (!save.getApprovalProcess().equals(oldApprovalProcess)){

                approvalProcessLogRepository.deleteByApprovalProcessId(save.getId());
                approvalProcessDetailRepository.deleteByApprovalProcessId(save.getId());

                ApprovalProcessLog approvalProcessLog=new ApprovalProcessLog();
                approvalProcessLog.setApprovalProcessId(save.getId());
                approvalProcessLog.setOldApprovalProcess(oldApprovalProcess);
                approvalProcessLog.setNewApprovalProcess(save.getApprovalProcess());
                approvalProcessLog.setOperationId(tokenRedisVo.getId());
                approvalProcessLog.setOperationTime(new Date());
                approvalProcessLogRepository.save(approvalProcessLog);

                String[] tagIds=save.getApprovalProcess().split(",");
                List<ApprovalProcessDetail> detailList=new ArrayList<>();
                for(String tagId : tagIds) {
                    ApprovalProcessDetail approvalProcessDetail = new ApprovalProcessDetail();
                    approvalProcessDetail.setApprovalProcessId(save.getId());
                    approvalProcessDetail.setTagId(Long.valueOf(tagId));
                    detailList.add(approvalProcessDetail);
                }

                approvalProcessDetailRepository.saveAll(detailList);


            }


        } catch (Exception e) {
            LOG.error(e.getMessage(),e);
            resultBean.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            resultBean.setMsg(e.getMessage());
        }
        return resultBean;
    }
    /*
     *显示所有部门标签
     */
    public ResultBean<Object> allDepartmentTag(String accessToken) {
        LOG.info("---DepartmentService allDepartmentTag accessToken={}", accessToken);
        ResultBean<Object> result = new ResultBean<>();
        result.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        result.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        TokenRedisVo tokenRedisVo=redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo==null){
                result.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                result.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return result;
            }
            List<DepartmentTag> all = departmentTagRepository.findAll();
            result.setResultData(all);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            result.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            result.setMsg(e.getMessage());
        }
        return result;
    }

    /*
     *查询当前登录企业节点下所有机构层级结构
     */
    public ResultBean<Object> findFlowPointCompany(String accessToken) {
        LOG.info("HouseManagerService findFlowPointCompany accessToken={}", accessToken);
        ResultBean<Object> resultBean = new ResultBean<>();
        resultBean.setCode(StatusCode.SUCCESS_CODE_10000.getErrorCode());
        resultBean.setMsg(StatusCode.SUCCESS_CODE_10000.getErrorMsg());
        resultBean.setResultData(Collections.emptyList());
        TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
        try {
            if (tokenRedisVo == null) {
                resultBean.setCode(StatusCode.ERROR_CODE_40001.getErrorCode());
                resultBean.setMsg(StatusCode.ERROR_CODE_40001.getErrorMsg());
                return resultBean;
            }
            Optional<Department> existDepartment = departmentRepository.findById(tokenRedisVo.getEnterpriseId());
            if (existDepartment == null) {
                return ResultBean.failedResultWithMsg("部门不存在或已删除");
            }
            DepartmentHierarchy existDepartmentHierarchy = hierarchyRepository.findByOrgId(tokenRedisVo.getEnterpriseId());
            if (existDepartmentHierarchy == null) {
                return ResultBean.failedResultWithMsg("部门机构层级关系不存在或已删除");
            }
            String sql = " SELECT id FROM ( SELECT t1.id,IF(FIND_IN_SET(parent_id, @pids) > 0,@pids := CONCAT(@pids, ',', id),0) AS ischild FROM ( SELECT id,parent_id FROM `saas_department_hierarchy` t ORDER BY parent_id, id ) t1,(SELECT @pids := ? ) t2 ) t3 WHERE ischild != 0 \n";
            List<Long> ids = jdbcTemplate.queryForList(sql, new Object[]{existDepartmentHierarchy.getId()}, Long.class);
            ids.add(existDepartmentHierarchy.getId());
            List<DepartmentHierarchy> treeDepartmentHierarchy = hierarchyRepository.findByIdIn(ids);
            List<Map<String, Object>> menuList = new LinkedList<Map<String, Object>>();
            findChild(menuList, treeDepartmentHierarchy);
            resultBean.setResultData(menuList);
        } catch (Exception e) {
            resultBean.setCode(StatusCode.ERROR_CODE_10001.getErrorCode());
            resultBean.setMsg(e.getMessage());
        }
        return resultBean;
    }

    private void findChild(List<Map<String, Object>> menuList, List<DepartmentHierarchy> list) {
        for (DepartmentHierarchy vo : list) {
            if (hasParent(vo.getParentId(), list)) {
                continue;
            }
            Map<String, Object> firstMap = new LinkedHashMap<String, Object>();
            firstMap.put("id", vo.getId());
            firstMap.put("orgId", vo.getOrgId());
            firstMap.put("parentId", vo.getParentId());
            firstMap.put("code", vo.getCode());
            firstMap.put("name", vo.getName());
            firstMap.put("tagId", vo.getTagId());
            DepartmentTag departmentTag = departmentTagRepository.findById(vo.getTagId()).get();
            firstMap.put("tagName", departmentTag.getTagName());
            firstMap.put("auditorUserId", vo.getAuditorUserId());
            firstMap.put("areaId", vo.getAreaId());
            menuList.add(firstMap);
            findChildMenus(firstMap, vo, list);
        }
    }

    /*
     *查找子类
     */
    private void findChildMenus(Map<String, Object> firstMap, DepartmentHierarchy parentVo, List<DepartmentHierarchy> list) {
        if (!hasChildren(parentVo.getId(), list)) {
            return;
        }
        List<Map<String, Object>> childList = new LinkedList<Map<String, Object>>();
        for (DepartmentHierarchy vo : list) {
            if (parentVo.getId().longValue() != vo.getParentId().longValue()) {
                continue;
            }
            Map<String, Object> childMap = new LinkedHashMap<String, Object>();
            childMap.put("id", vo.getId());
            childMap.put("orgId", vo.getOrgId());
            childMap.put("parentId", vo.getParentId());
            childMap.put("code", vo.getCode());
            childMap.put("name", vo.getName());
            childMap.put("tagId", vo.getTagId());
            DepartmentTag departmentTag = departmentTagRepository.findById(vo.getTagId()).get();
            childMap.put("tagName", departmentTag.getTagName());
            childMap.put("auditorUserId", vo.getAuditorUserId());
            childMap.put("areaId", vo.getAreaId());
            childList.add(childMap);
            firstMap.put("child", childList);
            if (hasChildren(parentVo.getId(), list)) {
                findChildMenus(childMap, vo, list);
            }
        }
    }

    /*
     *判断是否有父级
     */
    private boolean hasParent(Long id, List<DepartmentHierarchy> list) {
        for (DepartmentHierarchy vo : list) {
            if (id.longValue() != vo.getId().longValue()) {
                continue;
            }
            return true;
        }
        return false;
    }

    /*
     *判断是否有子集
     */
    private boolean hasChildren(Long id, List<DepartmentHierarchy> list) {
        for (DepartmentHierarchy vo : list) {
            if (id.longValue() != vo.getParentId().longValue()) {
                continue;
            }
            return true;
        }
        return false;
    }
}
